package com.easyJava.builder;

import com.easyJava.bean.Constants;
import com.easyJava.bean.FieldInfo;
import com.easyJava.bean.TableInfo;
import com.easyJava.utils.BufferedWriterUtils;
import com.easyJava.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

@Slf4j
public class BuildController {
    public static void execute(TableInfo tableInfo){
        File folder = new File(Constants.PATH_CONTROLLER);
        folder.mkdirs();
        String controllerName = tableInfo.getBeanName() + Constants.SUFFIX_CONTROLLER;
        String beanParamName = StringUtils.lowerFirstChar(tableInfo.getBeanName());
        String beanQueryParamName = StringUtils.lowerFirstChar(tableInfo.getBeanQueryName());
        String serviceName = tableInfo.getBeanName() + Constants.SUFFIX_SERVICE;

        File file = new File(folder, controllerName + Constants.FILE_SUFFIX_JAVA);

        try (
                OutputStream out = new FileOutputStream(file);
                OutputStreamWriter ow = new OutputStreamWriter(out, StandardCharsets.UTF_8);
                BufferedWriter bufferedWriter = new BufferedWriter(ow);
        ){
            BufferedWriterUtils bw = new BufferedWriterUtils(bufferedWriter);

            //生成包头
            bw.write("package " + Constants.PACKAGE_CONTROLLER + ";");
            bw.newLine();

            //导包
            bw.write("import " + Constants.PACKAGE_SERVICE + "." + serviceName + ";");
            bw.write("import " + Constants.PACKAGE_RESULT + ".Result;");
            bw.write("import " + Constants.PACKAGE_VO + ".PaginationResultVO;");
            bw.write("import " + Constants.PACKAGE_PO + "." + tableInfo.getBeanName() + ";");
            bw.write("import " + Constants.PACKAGE_QUERY + "." + tableInfo.getBeanQueryName() + ";");
            bw.newLine();
            bw.write("import java.util.List;");
            bw.write("import org.springframework.beans.factory.annotation.Autowired;");
            bw.write("import org.springframework.web.bind.annotation.RestController;");
            bw.write("import org.springframework.web.bind.annotation.*;");
            bw.newLine();

            //生成注释
            BuildComment.createClassComment(bw, tableInfo.getComment() + "Controller接口");
            //controller类
            bw.write("@RestController");
            bw.write("@RequestMapping(\"/" + beanParamName + "\")");
            bw.write("public class " + controllerName +"{");
            bw.newLine();

            //注入service
            BuildComment.createFieldComment(bw, tableInfo.getBeanName() + "Service对象");
            bw.write("\t@Autowired");
            bw.write("\tprivate " + serviceName + " " + StringUtils.lowerFirstChar(serviceName) + ";");
            bw.newLine();

            generateBaseMethod(bw, tableInfo);

            generateExtendMethod(bw, tableInfo);


            bw.write("}");
            bw.flush();
        }catch (Exception e){
            log.error("创建controller失败:{}", e);
        }
    }

    private static void generateBaseMethod(BufferedWriterUtils bw, TableInfo tableInfo) throws IOException{
        bw.newLine();
        String beanParamName = StringUtils.lowerFirstChar(tableInfo.getBeanName());
        String beanQueryParamName = StringUtils.lowerFirstChar(tableInfo.getBeanQueryName());
        String serviceName = StringUtils.lowerFirstChar(tableInfo.getBeanName() + Constants.SUFFIX_SERVICE);

        BuildComment.createMethodComment(bw, "新增");
        bw.write("\t@PostMapping");
        bw.write("\tpublic Result add(@RequestBody " + tableInfo.getBeanName() + " " + beanParamName + "){");
        bw.write("\t\t" + serviceName + ".add(" + beanParamName + ");");
        bw.write("\t\treturn Result.success();");
        bw.write("\t}");
        bw.newLine();

        BuildComment.createMethodComment(bw, "新增或修改");
        bw.write("\t@PutMapping");
        bw.write("\tpublic Result addOrUpdate(@RequestBody " + tableInfo.getBeanName() + " " + beanParamName + "){");
        bw.write("\t\t" + serviceName + ".addOrUpdate(" + beanParamName + ");");
        bw.write("\t\treturn Result.success();");
        bw.write("\t}");
        bw.newLine();

        BuildComment.createMethodComment(bw, "批量新增");
        bw.write("\t@PostMapping(\"/list\")");
        bw.write("\tpublic Result addBatch(@RequestBody List<" + tableInfo.getBeanName() + "> " + beanParamName + "List){");
        bw.write("\t\t" + serviceName + ".addBatch(" + beanParamName + "List);");
        bw.write("\t\treturn Result.success();");
        bw.write("\t}");
        bw.newLine();

        BuildComment.createMethodComment(bw, "批量新增或修改");
        bw.write("\t@PutMapping(\"/list\")");
        bw.write("\tpublic Result addOrUpdateBatch(@RequestBody List<" + tableInfo.getBeanName() + "> " + beanParamName + "List){");
        bw.write("\t\t" + serviceName + ".addOrUpdateBatch(" + beanParamName + "List);");
        bw.write("\t\treturn Result.success();");
        bw.write("\t}");
        bw.newLine();

        BuildComment.createMethodComment(bw, "查询");
        bw.write("\t@GetMapping");
        bw.write("\tpublic Result<List<" + tableInfo.getBeanName() + ">> getList(" + tableInfo.getBeanQueryName() + " " + beanQueryParamName + "){");
        bw.write("\t\tList<" + tableInfo.getBeanName() + "> list = " + serviceName + ".getList(" + beanQueryParamName + ");");
        bw.write("\t\treturn Result.success(list);");
        bw.write("\t}");
        bw.newLine();

        BuildComment.createMethodComment(bw, "分页查询");
        bw.write("\t@GetMapping(\"/page\")");
        bw.write("\tpublic Result<PaginationResultVO<" + tableInfo.getBeanName() + ">> page(" + tableInfo.getBeanQueryName() + " " + beanQueryParamName + "){");
        bw.write("\t\tPaginationResultVO<" + tableInfo.getBeanName() + "> result = " + serviceName + ".getPageList(" + beanQueryParamName + ");");
        bw.write("\t\treturn Result.success(result);");
        bw.write("\t}");
        bw.newLine();

    }

    private static void generateExtendMethod(BufferedWriterUtils bw, TableInfo tableInfo) throws IOException{
        bw.newLine();
        String beanParamName = StringUtils.lowerFirstChar(tableInfo.getBeanName());
        String beanQueryParamName = StringUtils.lowerFirstChar(tableInfo.getBeanQueryName());
        String serviceName = StringUtils.lowerFirstChar(tableInfo.getBeanName() + Constants.SUFFIX_SERVICE);

        Map<String, List<FieldInfo>> indexMap = tableInfo.getIndexMap();
        for(Map.Entry<String, List<FieldInfo>> entry : indexMap.entrySet()){
            List<FieldInfo> fieldInfoList = entry.getValue();
            StringBuffer methodNameSB = new StringBuffer();
            StringBuffer paramSB = new StringBuffer();
            StringBuffer invokeParamSB = new StringBuffer();
            int index = 0;
            for(FieldInfo fieldInfo : fieldInfoList){
                index++;
                methodNameSB.append(StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()));
                paramSB.append(fieldInfo.getJavaType()  + " "  + fieldInfo.getBeanFieldName());
                invokeParamSB.append(fieldInfo.getBeanFieldName());
                if(index < fieldInfoList.size()){
                    methodNameSB.append("And");
                    paramSB.append(", ");
                    invokeParamSB.append(", ");
                }
            }
            String methodName = methodNameSB.toString();
            String param = paramSB.toString();
            String invokeParam = invokeParamSB.toString();

            BuildComment.createMethodComment(bw, "根据" + methodName + "查询");
            bw.write("\t@GetMapping(\"/" + StringUtils.lowerFirstChar(methodName) + "\")");
            bw.write("\tpublic Result<" + tableInfo.getBeanName() + "> getBy" + methodName + "(@RequestBody " + tableInfo.getBeanName() + " " + beanParamName + "){");
            for (FieldInfo fieldInfo : fieldInfoList){
                bw.write("\t\t" + fieldInfo.getJavaType() + " " + fieldInfo.getBeanFieldName() + " = " + beanParamName + ".get" + StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()) + "();");
            }
            bw.write("\t\t" + tableInfo.getBeanName() + " res = " + serviceName + ".getBy" + methodName + "(" + invokeParam + ");");
            bw.write("\t\treturn Result.success(res);");
            bw.write("\t}");
            bw.newLine();

            BuildComment.createMethodComment(bw, "根据" + methodName + "修改");
            bw.write("\t@PutMapping(\"/" + StringUtils.lowerFirstChar(methodName) + "\")");
            bw.write("\tpublic Result updateBy" + methodName + "(@RequestBody " + tableInfo.getBeanName() + " " + beanParamName + "){");
            for (FieldInfo fieldInfo : fieldInfoList){
                bw.write("\t\t" + fieldInfo.getJavaType() + " " + fieldInfo.getBeanFieldName() + " = " + beanParamName + ".get" + StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()) + "();");
            }
            bw.write("\t\t" + serviceName + ".updateBy" + methodName + "(" + beanParamName + ", " + invokeParam + ");");
            bw.write("\t\treturn Result.success();");
            bw.write("\t}");
            bw.newLine();

            BuildComment.createMethodComment(bw, "根据" + methodName + "删除");
            bw.write("\t@DeleteMapping(\"/" + StringUtils.lowerFirstChar(methodName) + "\")");
            bw.write("\tpublic Result deleteBy" + methodName + "(@RequestBody " + tableInfo.getBeanName() + " " + beanParamName + "){");
            for (FieldInfo fieldInfo : fieldInfoList){
                bw.write("\t\t" + fieldInfo.getJavaType() + " " + fieldInfo.getBeanFieldName() + " = " + beanParamName + ".get" + StringUtils.upperFirstChar(fieldInfo.getBeanFieldName()) + "();");
            }
            bw.write("\t\t" + serviceName + ".deleteBy" + methodName + "(" + invokeParam + ");");
            bw.write("\t\treturn Result.success();");
            bw.write("\t}");
            bw.newLine();
        }
    }
}
